# -*- coding: utf-8 -*-
import json
import os.path
import sys
import time
import re

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.Qt import *
from PyQt5.QtGui import *

from client.pages.ChatWin import Ui_ChatWin
from client.pages.MyPart import Bubble, ListItem
from client.pages.EmojiPage import EmojiPage

from client.func.TimeCalc import is_need_show_time
from client.func.ClientHttp import get_user_info_post, get_history_post, send_message_post, get_group_info_post

import client.pages.FriendInfoPage as FP
import client.pages.global_win as gw

root = "./"


def load_history(uid, target, mode):
    if mode == "friend":
        history_path = root + "client/history/u" + uid + "/chat/u" + target + ".json"
    else:
        history_path = root + "client/history/u" + uid + "/chat/g" + target + ".json"
    get_history_post(uid, target, mode)  # 获取聊天历史
    if os.path.exists(history_path):
        with open(history_path, "r", encoding="utf-8") as f:
            chat_dicts = json.load(f)["history"]
            return chat_dicts
    else:
        return []


class UpdateThread(QThread):
    update_signal = pyqtSignal()
    bubble_signal = pyqtSignal(list)

    def __init__(self):
        super(UpdateThread, self).__init__()
        self.uid = ""
        self.target = ""
        self.mode = ""

    def run(self):
        while True:
            chat_dicts = load_history(self.uid, self.target, self.mode)
            if chat_dicts:
                self.bubble_signal.emit(chat_dicts)
            self.update_signal.emit()
            time.sleep(1)


class UploadThread(QThread):
    """发送消息线程"""
    def __init__(self):
        super(UploadThread, self).__init__()
        self.uid = ""
        self.target = ""
        self.mode = ""
        self.msg_dic = None
        self.bubble = None

    def run(self):
        self.bubble.widget.status = "waiting"
        if send_message_post(self.uid, self.target, self.mode, self.msg_dic):
            self.bubble.widget.status = "finish"
        else:
            self.bubble.widget.status = "error"


class ChatPage(QMainWindow, Ui_ChatWin):
    def __init__(self):
        super(ChatPage, self).__init__()
        self.setupUi(self)
        self.textEdit.verticalScrollBar().style().polish(self.textEdit.verticalScrollBar())
        self.bubblesWidget.verticalScrollBar().style().polish(self.bubblesWidget.verticalScrollBar())
        self.membersWidget.verticalScrollBar().style().polish(self.membersWidget.verticalScrollBar())
        self.myname = u"我"
        self.myuid = ""
        self.myimg_path = "user_default.png"
        self.target = ""
        self.category = "friend"  # friend, group
        self.toBottom = True
        self.show_emoji = False
        self.bubble_num = 0  # 联网获取的消息数量
        self.emoji_win = EmojiPage()

        self.chat_dicts = []
        self.member_dicts = []
        self.bubble_list = []
        self.member_list = []
        self.send_button.clicked.connect(self.OnSend)
        self.file_button.clicked.connect(self.OnOpenFile)
        self.emoji_button.clicked.connect(self.OnEmoji)
        self.emoji_win.tableWidget.itemClicked.connect(self.AddEmoji)
        self.bottom_Button.clicked.connect(self.OnToBottom)
        self.bubblesWidget.verticalScrollBar().sliderReleased.connect(self.OnScrollBarClicked)
        self.membersWidget.itemClicked.connect(self.OnItemClicked)

        self.update_thread = UpdateThread()
        self.update_thread.update_signal.connect(self.scroll_updata)
        self.update_thread.bubble_signal.connect(self.bubble_update)
        self.send_thread_list = []

    def OnItemClicked(self, item):
        uid = item.uid
        if item.category == "friend":
            if "u" + uid not in gw.get_keys():
                win = FP.FriendInfoPage()
                win.uid = uid
                win.myuid = self.myuid
                gw.set_value("u" + uid, win)
                win.update()
                win.show()
            else:
                gw.get_value("u" + uid).update()
                gw.get_value("u" + uid).show()

    def AddEmoji(self, item):
        self.textEdit.insertPlainText(item.emojiIcon.text())

    def OnEmoji(self):
        if self.show_emoji:
            self.show_emoji = False
            self.emoji_win.hide()
        else:
            self.emoji_win.move(self.pos()+self.emoji_button.pos()-QPoint(-20, 200))
            self.show_emoji = True
            self.emoji_win.show()

    def get_chat_info(self):
        members = []
        if self.category == "friend":
            data = get_user_info_post(self.target)
            if data:
                members.append({
                    "name": self.myname,
                    "uid": self.myuid,
                    "img_path": self.myimg_path
                })
                members.append({
                    "name": data[1],
                    "uid": self.target,
                    "img_path": data[2]
                })
                return data[1], data[2], members
            else:
                return u"好友", "user_default.png", []
        else:
            data = get_group_info_post(self.target)
            if data:
                group_member = data["members"]
                for member in group_member:
                    member_data = get_user_info_post(member)
                    if member_data:
                        members.append({
                            "name": member_data[1],
                            "uid": member,
                            "img_path": member_data[2]
                        })
                return data["name"], data["img"], members
            else:
                return u"群聊", "group_default.png", []

    def clear_list(self):
        self.bubble_list.clear()
        self.member_list.clear()
        self.bubblesWidget.clear()
        self.membersWidget.clear()

    def import_all_bubble(self):
        for i, dic in enumerate(self.chat_dicts):
            bubble = Bubble()
            bubble.init_data(dic)
            if i:
                bubble.widget.show_time = is_need_show_time(self.chat_dicts[i - 1]["time"], self.chat_dicts[i]["time"])
            self.bubblesWidget.addItem(bubble)
            self.bubblesWidget.setItemWidget(bubble, bubble.widget)
            self.bubble_list.append(bubble)
            self.bubble_num += 1

    def import_member(self):
        for dic in self.member_dicts:
            item = ListItem()
            item.name = dic["name"]
            item.uid = dic["uid"]
            item.category = "friend"
            item.img_path = root + "client/.cache/img_buf/" + dic["img_path"]
            item.set_img(item.img_path)
            item.max_name = 7
            item.update()
            self.membersWidget.addItem(item)
            self.membersWidget.setItemWidget(item, item.widget)
            self.member_list.append(item)

    def bubble_update(self, history):
        """刷新消息"""
        self.chat_dicts = history  # 导入历史记录
        right_num = len(self.chat_dicts)
        current_num = len(self.bubble_list)
        if not self.bubble_num == current_num:  # 移除多余的气泡
            for i in range(0, current_num):
                if self.bubble_list[i].widget.status == "finish":
                    del self.bubble_list[i]  # 确保气泡框中的气泡全是列表self.chat_dicts中的
                    self.bubblesWidget.takeItem(i)
        for i in range(self.bubble_num, right_num):
            bubble = Bubble()
            bubble.init_data(self.chat_dicts[i])
            if i:
                bubble.widget.show_time = is_need_show_time(self.chat_dicts[i - 1]["time"], self.chat_dicts[i]["time"])
            self.bubblesWidget.addItem(bubble)
            self.bubblesWidget.setItemWidget(bubble, bubble.widget)
            self.bubble_list.append(bubble)
            self.bubble_num += 1

    def init_update(self):
        """打开聊天窗口时第一次刷新页面"""
        try:
            data = get_user_info_post(self.myuid)
            if data:
                self.myname = data[1]
                self.myimg_path = data[2]
            self.chat_dicts = load_history(self.myuid, self.target, self.category)  # 导入历史记录
            chat_name, chat_img, self.member_dicts = self.get_chat_info()  # 获取聊天窗标题，头像，成员列表
            self.setWindowTitle(chat_name)
            img_path = root + "client/.cache/img_buf/" + chat_img
            if os.path.exists(img_path):
                icon = QtGui.QIcon()
                icon.addPixmap(QtGui.QPixmap(img_path), QIcon.Normal, QIcon.On)
                self.setWindowIcon(icon)
            self.clear_list()
            self.import_member()
            self.import_all_bubble()
            self.update_thread.uid = self.myuid
            self.update_thread.target = self.target
            self.update_thread.mode = self.category
            self.update_thread.start()
        except Exception as e:
            print(self.target, "init_update:", e)

    def split_msg(self):
        html_data = self.textEdit.toHtml()
        msg_list = []
        msg_html_data = html_data[432:-18]
        alinks = re.findall(r'<a href=[\s\S]*?/></a>', msg_html_data)
        if alinks:
            texts = self.textEdit.toPlainText().split("￼ ")  # 不知道是啥符号，但是超链接转纯文本后就会变成这个
        else:
            texts = [self.textEdit.toPlainText()]
        for text in texts:
            if text:
                msg_list.append(["text", text])
        for alink in alinks:
            if alink:
                if 'title="img:' in alink:
                    msg_list.append(["img", alink])
                elif 'title="file:' in alink:
                    msg_list.append(["file", alink])
        return msg_list

    def OnSend(self):
        # print(self.textEdit.toHtml())
        # print(self.textEdit.toPlainText())
        msg_list = self.split_msg()
        for msg in msg_list:
            if msg[0] == "text":
                dic = {
                    "uid": self.myuid,
                    "name": self.myname,
                    "text": msg[1],
                    "img_path": self.myimg_path,
                    "time": str(int(time.time())),
                    "isMe": True,
                    "bubble_type": "text"
                }
            elif msg[0] == "img":
                dic = {
                    "uid": self.myuid,
                    "name": self.myname,
                    "text": msg[1],
                    "img_path": self.myimg_path,
                    "time": str(int(time.time())),
                    "isMe": True,
                    "bubble_type": "img"
                }
            else:
                dic = {
                    "uid": self.myuid,
                    "name": self.myname,
                    "text": msg[1],
                    "img_path": self.myimg_path,
                    "time": str(int(time.time())),
                    "isMe": True,
                    "bubble_type": "file"
                }
            bubble = Bubble()
            bubble.init_data(dic)
            self.bubblesWidget.addItem(bubble)
            self.bubblesWidget.setItemWidget(bubble, bubble.widget)
            self.bubble_list.append(bubble)
            upload_thread = UploadThread()
            upload_thread.uid = self.myuid
            upload_thread.target = self.target
            upload_thread.mode = self.category
            upload_thread.msg_dic = dic
            upload_thread.bubble = bubble
            upload_thread.start()
            self.send_thread_list.append(upload_thread)
            self.textEdit.clear()
            self.toBottom = True
            self.bubblesWidget.scrollToBottom()

    def OnOpenFile(self):
        file_path, file_type = QFileDialog.getOpenFileName(self, "选择文件", "./", "All Files (*);")
        file_name = os.path.basename(file_path)
        if file_name:
            html_data = '<a href={}><img src="{}" width="{}" height="{}" title="file:{}"/></a> '.format(
                file_path + "?file",
                root + "client/src/file_type.png",
                50, 50,
                file_name
            )
            fragment = QTextDocumentFragment.fromHtml(html_data)
            self.textEdit.textCursor().insertFragment(fragment)
            self.textEdit.textCursor().insertText("")  # 不加这句之后添加文本会带超链接

    def OnToBottom(self):
        self.toBottom = True
        self.bubblesWidget.scrollToBottom()

    def scroll_updata(self):
        if self.toBottom:
            self.bubblesWidget.scrollToBottom()

    def resize_bubble(self):
        """改变气泡宽度"""
        for bubble in self.bubble_list:
            bubble.widget.set_width(self.bubblesWidget.width())
        self.bubblesWidget.scrollToBottom()

    def resizeEvent(self, a0: QtGui.QResizeEvent) -> None:
        """窗口大小改变事件"""
        try:
            self.resize_bubble()
        except:
            self.bubble_list = []

    def wheelEvent(self, a0: QtGui.QWheelEvent) -> None:
        self.toBottom = False

    def OnScrollBarClicked(self):
        self.toBottom = False

    def closeEvent(self, a0: QtGui.QCloseEvent) -> None:
        self.send_thread_list.clear()
        self.update_thread.terminate()
        self.emoji_win.close()
        self.close()


if __name__ == "__main__":
    root = "../../"
    app = QApplication(sys.argv)
    myWin = ChatPage()
    myWin.show()
    sys.exit(app.exec_())
